<template>
  <div>
    <vxe-table
      border="inner"
      :column-config="{ resizable: true }"
      :tree-config="{
        transform: true,
        rowField: 'id',
        parentField: 'parentId',
        showIcon: true,
      }"
      :data="menuPermissionList"
    >
      <vxe-column field="name" title="名称" tree-node></vxe-column>
      <vxe-column field="code" title="权限值" />
      <vxe-column field="toCode" title="跳转权限值" />
      <vxe-column title="操作">
        <template #default="{ row }">
          <el-button
            :disabled="row.level === 4"
            type="primary"
            :icon="Plus"
            size="small"
            @click="toAddPermission(row)"
            :title="getAddTitle(row.level)"
          />

          <el-button
            type="primary"
            :icon="Edit"
            size="small"
            :disabled="row.level === 1"
            @click="toUpdatePermission(row)"
            :title="row.level === 4 ? '修改功能' : '修改菜单'"
          />

          <el-button
            :disabled="row.level === 1"
            type="danger"
            :icon="Delete"
            size="small"
            @click="removePermission(row)"
            title="删除"
          />
        </template>
      </vxe-column>
    </vxe-table>


    <el-dialog v-model="dialogVisible" :title="dialogTitle" @close="resetData">
      <el-form
        ref="permissionRef"
        :model="permission"
        :rules="permissionRules"
        label-width="120px"
      >
        <el-form-item label="名称" prop="name">
          <el-input v-model="permission.name" />
        </el-form-item>

        <el-form-item label="功能权限值" prop="code">
          <el-input v-model="permission.code" />
        </el-form-item>

        <el-form-item
          label="跳转路由权限值"
          prop="toCode"
          v-if="permission.level === 4"
        >
          <el-input v-model="permission.toCode" />
        </el-form-item>
      </el-form>

      <template #footer>
        <el-button @click="resetData">取 消</el-button>
        <el-button type="primary" @click="addOrUpdatePermission"
          >确 定</el-button
        >
      </template>
    </el-dialog>
  </div>
</template>

<script lang="ts">
export default {
  name: "Permission",
};
</script>

<script lang="ts" setup>
import {
  ElButton,
  ElDialog,
  ElForm,
  ElFormItem,
  ElInput,
  type FormInstance,
  ElMessage,
  ElMessageBox,
} from "element-plus";
import { Plus, Edit, Delete } from "@element-plus/icons-vue";
import { reactive, ref, computed, onMounted } from "vue";
import type {
  PermissionModel,
  PermissionLevelModel,
} from "@/api/acl/model/permissionModel";
import {
  getPermissionListApi,
  removePermissionApi,
  saveOrUpdatePermissionApi,
} from "@/api/acl/permission";

const permissionRef = ref<FormInstance>();
type TreeGrid = {
  name: null | string;
  parentId: null | number;
  code: null | string;
  select: null | boolean;
  level: null | number;
  id: null | string;
  type: 1 | 2;
  toCode?: string;
};
const menuPermissionList = ref<TreeGrid[]>([]);
const expandKeys = ref<string[]>([]);
const dialogVisible = ref<boolean>(false);
const permission = reactive<PermissionModel>({
  // 要操作的菜单权限对象
  type: 1,
  level: 0,
  name: "",
  code: "",
  toCode: "",
});

onMounted(() => {
  fetchPermissionList();
});

/* 
  动态计算得到Dialog的标题
  */
const dialogTitle = computed(() => {
  const { id, level } = permission;
  if (id) {
    return level === 4 ? "修改功能" : "修改菜单";
  } else {
    return level === 4 ? "添加功能" : "添加菜单";
  }
});

/* 
  根据权限的等级来计算确定校验规则
  */
const permissionRules = computed(() => {
  // 菜单权限校验的规则
  const menuRules = {
    name: [{ required: true, message: "名称必须输入" }],
    code: [{ required: true, message: "权限值必须输入" }],
  };
  // 按钮功能权限校验的规则
  const btnRules = {
    name: [{ required: true, message: "名称必须输入" }],
    code: [{ required: true, trigger: "blur", message: "功能权限值必须输入" }],
  };
  return permission.level === 4 ? btnRules : menuRules;
});

/* 
  根据级别得到要显示的添加dialog的标题
  */
const getAddTitle = (level: number) => {
  if (level === 1 || level === 2) {
    return "添加菜单";
  } else if (level === 3) {
    return "添加功能";
  }
};

/* 
  请求获取权限菜单数据列表
  */
const fetchPermissionList = async () => {
  const result = await getPermissionListApi();
  arborescence(result.children, 1);
  expandKeys.value = [menuPermissionList.value[0].id as string];
};
// 将获取到的数据该为vxe树形列表数据
const arborescence = (result: any, Idx: number) => {
  result.forEach((item: any) => {
    if (item.level === 1) {
      menuPermissionList.value.push({
        name: item.name as string,
        parentId: null,
        code: item.code as string,
        select: item.select as boolean,
        id: item.id as string,
        level: item.level,
        type: item.type,
        toCode: item.toCode,
      });
    } else {
      menuPermissionList.value.push({
        level: item.level,
        name: item.name as string,
        parentId: Idx,
        code: item.code as string,
        select: item.select as boolean,
        id: item.id as string,
        type: item.type,
        toCode: item.toCode,
      });
    }
    if (item.children && item.children.length > 0) {
      arborescence(item.children, item.id);
    }
  });
};
/* 
  显示添加权限的界面(菜单或功能)
  */
const toAddPermission = (row: PermissionModel) => {
  dialogVisible.value = true;
  permission.pid = row.id; // pid ==> parentId 父权限数据的id
  permission.level = (row.level + 1) as PermissionLevelModel;
  permission.type = permission.level === 4 ? 2 : 1;

  // 清除校验(必须在界面更新之后)
  // 注意: 校验规则是动态的, nextTick清除后还会显示错误信息, 应该是在nextTick后进行了校验
  /* nextTick(() => {
      console.log('nextTick')
      permissionRef.value?.clearValidate()
    }) */
  setTimeout(() => {
    permissionRef.value?.clearValidate();
  }, 0);
};

/* 
  显示菜单添加或更新的dialog
  */
const toUpdatePermission = (row: PermissionModel) => {
  dialogVisible.value = true;
  Object.assign(permission, row);
  permission.type = permission.level === 4 ? 2 : 1;

  // 清除校验(必须在界面更新之后)
  // nextTick(() => permissionRef.value?.clearValidate())
  setTimeout(() => {
    permissionRef.value?.clearValidate();
  }, 0);
};

/* 
  删除某个权限节点
  */
const removePermission = (permission: PermissionModel) => {
  ElMessageBox.confirm("此操作将永久删除该记录, 是否继续?", "提示", {
    type: "warning",
  })
    .then(async () => {
      await removePermissionApi(permission.id as string);
      ElMessage.success("删除成功!");
      fetchPermissionList();
    })
    .catch((error: any) => {
      if (error === "cancel") {
        ElMessage({
          type: "info",
          message: "已取消删除",
        });
      }
    });
};

/* 
  添加或更新功能权限
  */
const addOrUpdatePermission = () => {
  permissionRef.value?.validate(async (valid: any) => {
    if (valid) {
      const { id } = permission;

      await saveOrUpdatePermissionApi(permission);
      ElMessage.success(`${id ? "修改" : "添加"}成功!`);
      resetData();
      fetchPermissionList();
    }
  });
};

/* 
  重置数据
  */
const resetData = () => {
  dialogVisible.value = false;
  Object.assign(permission, {
    type: 1,
    level: 0,
    name: "",
    code: "",
    toCode: "",
  });
};
</script>
